package cn.com.xf.web.controller;

import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.nio.channels.FileChannel;
import java.util.ArrayList;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.validation.Valid;

import org.apache.commons.lang.StringUtils;
import org.apache.commons.lang.time.DateFormatUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.stereotype.Controller;
import org.springframework.validation.BindingResult;
import org.springframework.validation.ObjectError;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.ResponseBody;
import org.springframework.web.servlet.ModelAndView;

import cn.com.xf.common.AbstractBaseController;
import cn.com.xf.common.ConfigUtil;
import cn.com.xf.common.Constants;
import cn.com.xf.common.PinyinUtils;
import cn.com.xf.common.StringUtil;
import cn.com.xf.domain.TblApiApp;
import cn.com.xf.service.TblApiBarService;
import cn.com.xf.utils.encode.EncrypTool;
import cn.com.xf.web.PageModel;
import cn.com.xf.web.XFMappingJacksonJsonView;
import cn.com.xf.web.form.AppForm;
import cn.com.xf.web.form.BarForm;

@Controller
@RequestMapping("/app")
public class APPController extends AbstractBaseController {

	@Autowired
	private TblApiBarService tbBarService;

	@RequestMapping
	public ModelAndView index(HttpServletRequest request, HttpServletResponse response, BarForm form) throws Exception {
		form.setTab("bar");
		ModelAndView mv = new ModelAndView("/bar/index", Constants.FORM_COMMAND_KEY, form);
		return mv;
	}

	@RequestMapping(value = "/add")
	public ModelAndView add(HttpServletRequest request, HttpServletResponse response, AppForm form) throws Exception {
		ModelAndView mv = new ModelAndView("/app/add", Constants.FORM_COMMAND_KEY, form);
		return mv;
	}

	@RequestMapping(value = "/doAdd")
	public ModelAndView doAdd(HttpServletRequest request, HttpServletResponse response, @Valid AppForm form,
			BindingResult result) throws Exception {
		ModelAndView mv = new ModelAndView("/app/add_result", Constants.FORM_COMMAND_KEY, form);

		// 1.错误检查
		List<ObjectError> errorList = null;
		if (result.hasErrors()) {
			errorList = result.getAllErrors();
			String errorJson = errorToJson(errorList);
			mv.addObject("errorJson", errorJson);
			return mv;
		}
		// 2.提取临时文件中的文件
		// 2.1空值检查
		String tempFileId = form.getTempFileId();
		if (StringUtils.isBlank(form.getTempFileId())) {
			return null;
		}
		// 2.2获取临时文件列表
		TblApiApp app = new TblApiApp();
		String formalFileName = "";
		String tempFilesPath = servletContext.getRealPath("/") + Constants.UPLOAD_PATH_TEMP;
		File dir = new File(tempFilesPath);
		File file[] = dir.listFiles();
		// 2.3转存到正式的目录
		for (File f : file) {
			if (f.isFile()) {
				String allname = f.getName();
				if (allname.contains(Constants.UPLOAD_TEMP_SPILT)) {
					String name = allname.split(Constants.UPLOAD_TEMP_SPILT)[0];
					if (tempFileId.equalsIgnoreCase(name)) {
						formalFileName = DateFormatUtils.format(new Date(), "yyyyMMddHHmmss") + "_"
								+ PinyinUtils.converterToSpell(allname.split(Constants.UPLOAD_TEMP_SPILT)[1]);
						String absoluteFlvPath = ConfigUtil.getValue(Constants.ABSOLUTE_ROOT_NAME) + File.separator
								+ Constants.ABSOLUTE_ROOT_APP_PATH;
						File flvFile = new File(absoluteFlvPath);
						if (!flvFile.exists()) {
							flvFile.mkdirs();
						}
						File siteFormalFile = new File(absoluteFlvPath, formalFileName);
						fileChannelCopy(f, siteFormalFile);
					}
				}
			}
		}
		if (StringUtils.isBlank(formalFileName)) {
			return null;
		}

		if (result.hasErrors()) {
			errorList = result.getAllErrors();
			// 将错误信息Json化
			String errorJson = errorToJson(errorList);
			mv.addObject("errorJson", errorJson);
			return mv;
		}
		// 3.存储
		app.setCompany(form.getCompanyName());
		app.setAppOs(form.getAppOS());
		app.setAppVersion(form.getAppVersion());
		app.setType(form.getAppType());
		app.setStatus(form.getAppStatus());

		app.setAppDir(formalFileName);
		app.setAddTime(new Date());
		app.setAddTimeStr(DateFormatUtils.format(new Date(), "yyyy-MM-dd HH:mm:ss"));
		app.setAddUser(SecurityContextHolder.getContext().getAuthentication().getName());
		tbBarService.insertApiApp(app);
		mv.addObject("status", "SUCCESS");
		return mv;
	}

	@RequestMapping(value = "/manageList")
	public ModelAndView manageList(HttpServletRequest requets, HttpServletResponse response, AppForm form)
			throws Exception {
		ModelAndView mv = new ModelAndView("/app/manage_app", Constants.FORM_COMMAND_KEY, form);
		String companyName = StringUtil.StringFilter(form.getCompanyName());
		String appType = StringUtil.StringFilter(form.getAppType());
		String appStatus = StringUtil.StringFilter(form.getAppStatus());
		form.setCompanyName(companyName);
		form.setAppType(appType);
		form.setAppStatus(appStatus);

		int count = tbBarService.selectAppCount(companyName, appType, appStatus);
		if (count == 0) {
			return mv;
		}

		int pageNum = 1;
		if (StringUtils.isNotBlank(form.getPageNum())) {
			pageNum = Integer.valueOf(form.getPageNum());
		}
		PageModel pageModel = new PageModel(count, PageModel.DEFAULT_PAGE_SIZE, pageNum, form);
		int begin = pageModel.getBegin();
		int pageSize = pageModel.getPageSize();

		String orderByField = "ADD_TIME";
		String orderByMode = "DESC";
		if (StringUtils.isNotBlank(form.getOrderByField()) && StringUtils.isNotBlank(form.getOrderByMode())) {
			if ("appOS".equalsIgnoreCase(form.getOrderByField())) {
				orderByField = "APP_OS";
			}
			if ("appType".equalsIgnoreCase(form.getOrderByField())) {
				orderByField = "TYPE";
			}
			if ("appStatus".equalsIgnoreCase(form.getOrderByField())) {
				orderByField = "STATUS";
			}
			if ("addTime".equalsIgnoreCase(form.getOrderByField())) {
				orderByField = "ADD_TIME";
			}
			if ("asc".equalsIgnoreCase(form.getOrderByMode()) || "desc".equalsIgnoreCase(form.getOrderByMode())) {
				orderByMode = form.getOrderByMode();
			}
		}
		List<TblApiApp> list = tbBarService.selectApp(begin, pageSize, orderByField, orderByMode, companyName, appType,
				appStatus);
		mv.addObject("list", list);
		return mv;
	}

	@RequestMapping(value = "/doDelete")
	public ModelAndView doDelete(HttpServletRequest request, HttpServletResponse response, AppForm form)
			throws Exception {
		String idStr = form.getId();
		String realId = "";
		if (StringUtils.isNotBlank(idStr)) {
			realId = EncrypTool.dencode(idStr);
		}
		int result = tbBarService.deleteAppById(realId);
		Map map = new HashMap<String, String>();
		if (result < 0) {
			map.put("status", "FAILD");
		} else if (result >= 0) {
			map.put("status", "SUCCESS");
		}
		ModelAndView mv = new ModelAndView(new XFMappingJacksonJsonView(), map);
		return mv;
	}

	@RequestMapping(value = "/edit")
	public ModelAndView editPage(HttpServletRequest request, HttpServletResponse response, AppForm form)
			throws Exception {
		String idStr = form.getId();
		String realId = "";
		if (StringUtils.isNotBlank(idStr)) {
			realId = EncrypTool.dencode(idStr);
		}
		ModelAndView mv = new ModelAndView("/app/edit", Constants.FORM_COMMAND_KEY, form);
		TblApiApp app = tbBarService.selectAppById(realId);
		mv.addObject("app", app);
		return mv;
	}

	@RequestMapping(value = "/doEdit")
	public ModelAndView doEdit(HttpServletRequest request, HttpServletResponse response, @Valid AppForm form,
			BindingResult result) throws Exception {
		ModelAndView mv = new ModelAndView("/app/edit_result", Constants.FORM_COMMAND_KEY, form);
		// 1.错误检查
		List<ObjectError> errorList = null;
		if (result.hasErrors()) {
			errorList = result.getAllErrors();
			String errorJson = errorToJson(errorList);
			mv.addObject("errorJson", errorJson);
			return mv;
		}
		String idStr = form.getId();
		String realId = "";
		if (StringUtils.isNotBlank(idStr)) {
			realId = EncrypTool.dencode(idStr);
		}
		TblApiApp app = tbBarService.selectAppById(realId);
		// 2.提取临时文件中的文件
		// 2.1空值检查
		String tempFileId = form.getTempFileId();
		String formalFileName = "";
		if (!StringUtils.isBlank(form.getTempFileId())) {
			// 2.2获取临时文件列表
			formalFileName = "";
			String tempFilesPath = servletContext.getRealPath("/") + Constants.UPLOAD_PATH_TEMP;
			File dir = new File(tempFilesPath);
			File file[] = dir.listFiles();
			// 2.3转存到正式的目录
			for (File f : file) {
				if (f.isFile()) {
					String allname = f.getName();
					if (allname.contains(Constants.UPLOAD_TEMP_SPILT)) {
						String name = allname.split(Constants.UPLOAD_TEMP_SPILT)[0];
						if (tempFileId.equalsIgnoreCase(name)) {
							formalFileName = DateFormatUtils.format(new Date(), "yyyyMMddHHmmss") + "_"
									+ PinyinUtils.converterToSpell(allname.split(Constants.UPLOAD_TEMP_SPILT)[1]);
							String absoluteFlvPath = ConfigUtil.getValue(Constants.ABSOLUTE_ROOT_NAME) + File.separator
									+ Constants.ABSOLUTE_ROOT_APP_PATH;
							File flvFile = new File(absoluteFlvPath);
							if (!flvFile.exists()) {
								flvFile.mkdirs();
							}
							File siteFormalFile = new File(absoluteFlvPath, formalFileName);
							fileChannelCopy(f, siteFormalFile);
						}
					}
				}
			}
			if (StringUtils.isBlank(formalFileName)) {
				return null;
			}
			app.setAppDir(formalFileName);
		}

		if (result.hasErrors()) {
			errorList = result.getAllErrors();
			// 将错误信息Json化
			String errorJson = errorToJson(errorList);
			mv.addObject("errorJson", errorJson);
			return mv;
		}
		// 3.存储
		app.setCompany(form.getCompanyName());
		app.setAppOs(form.getAppOS());
		app.setAppVersion(form.getAppVersion());
		app.setType(form.getAppType());
		app.setStatus(form.getAppStatus());

		app.setUpdateTimeStr(DateFormatUtils.format(new Date(), "yyyy-MM-dd HH:mm:ss"));
		app.setUpdateUser(SecurityContextHolder.getContext().getAuthentication().getName());
		tbBarService.updateApiApp(app);
		mv.addObject("status", "SUCCESS");
		return mv;
	}

	@RequestMapping(value = "/getBrand")
	@ResponseBody
	public List<Map<String, String>> getAllBrand(HttpServletRequest request, HttpServletResponse response, BarForm form)
			throws Exception {
		List<Map<String, String>> list = new ArrayList<Map<String, String>>();
		for (String key : Constants.APP_COMPANY_MAP.keySet()) {
			Map<String, String> map = new HashMap<String, String>();
			map.put("id", key);
			map.put("type", Constants.APP_COMPANY_MAP.get(key));
			list.add(map);
		}
		return list;
	}

	@RequestMapping(value = "/getOS")
	@ResponseBody
	public List<Map<String, String>> getOS(HttpServletRequest request, HttpServletResponse response, BarForm form)
			throws Exception {
		List<Map<String, String>> list = new ArrayList<Map<String, String>>();
		for (String key : Constants.APP_OS_TYPE_MAP.keySet()) {
			Map<String, String> map = new HashMap<String, String>();
			map.put("id", key);
			map.put("type", Constants.APP_OS_TYPE_MAP.get(key));
			list.add(map);
		}
		return list;
	}

	@RequestMapping(value = "/getAPPType")
	@ResponseBody
	public List<Map<String, String>> getAppType(HttpServletRequest request, HttpServletResponse response, BarForm form)
			throws Exception {
		List<Map<String, String>> list = new ArrayList<Map<String, String>>();
		for (String key : Constants.APP_TYPE_MAP.keySet()) {
			Map<String, String> map = new HashMap<String, String>();
			map.put("id", key);
			map.put("type", Constants.APP_TYPE_MAP.get(key));
			list.add(map);
		}
		return list;
	}

	@RequestMapping(value = "/getStatusType")
	@ResponseBody
	public List<Map<String, String>> getStatusType(HttpServletRequest request, HttpServletResponse response,
			BarForm form) throws Exception {
		List<Map<String, String>> list = new ArrayList<Map<String, String>>();
		for (String key : Constants.APP_STATUS_MAP.keySet()) {
			Map<String, String> map = new HashMap<String, String>();
			map.put("id", key);
			map.put("type", Constants.APP_STATUS_MAP.get(key));
			list.add(map);
		}
		return list;
	}

	/**
	 * 
	 * @param s源文件
	 * @param t目标文件
	 */
	private void fileChannelCopy(File s, File t) {
		FileInputStream fi = null;
		FileOutputStream fo = null;
		FileChannel in = null;
		FileChannel out = null;
		try {
			fi = new FileInputStream(s);
			fo = new FileOutputStream(t);
			in = fi.getChannel();// 得到对应的文件通道
			out = fo.getChannel();// 得到对应的文件通道
			in.transferTo(0, in.size(), out);// 连接两个通道，并且从in通道读取，然后写入out通道
		} catch (IOException e) {
			e.printStackTrace();
		} finally {
			try {
				fi.close();
				in.close();
				fo.close();
				out.close();
			} catch (IOException e) {
				e.printStackTrace();
			}
		}
	}
}
